import React, { useEffect, useRef, useState } from 'react';
import './styles.css';

/**
 * VirtualList组件的属性接口
 * @interface VirtualListProps
 * @property {number} itemHeight - 每个列表项的固定高度（像素）
 * @property {number} totalCount - 列表项的总数量
 * @property {(index: number) => React.ReactNode} renderItem - 渲染列表项的函数
 * @property {number} containerHeight - 可视区域容器的高度（像素）
 * @property {number} [overscan=3] - 可视区域外预渲染的项数
 */
interface VirtualListProps {
  itemHeight: number;
  totalCount: number;
  renderItem: (index: number) => React.ReactNode;
  containerHeight: number;
  overscan?: number;
}

/**
 * 虚拟列表组件
 * 通过只渲染可视区域内的项目来优化长列表的性能
 * @param {VirtualListProps} props - 组件属性
 */
const VirtualList: React.FC<VirtualListProps> = ({
  itemHeight,
  totalCount,
  renderItem,
  containerHeight,
  overscan = 3
}) => {
  // 记录容器的滚动位置
  const [scrollTop, setScrollTop] = useState(0);
  // 容器的引用，用于获取滚动信息
  const containerRef = useRef<HTMLDivElement>(null);

  // 计算可视区域的起始和结束索引
  const visibleStartIndex = Math.floor(scrollTop / itemHeight);
  const visibleEndIndex = Math.min(
    Math.ceil((scrollTop + containerHeight) / itemHeight),
    totalCount
  );

  // 添加overscan以提高滚动体验，预渲染可视区域外的项目
  const startIndex = Math.max(0, visibleStartIndex - overscan);
  const endIndex = Math.min(totalCount, visibleEndIndex + overscan);

  // 生成需要渲染的项目数组
  const items = [];
  for (let i = startIndex; i < endIndex; i++) {
    items.push(
      <div
        key={i}
        style={{
          position: 'absolute',
          top: `${i * itemHeight}px`,
          height: `${itemHeight}px`,
          width: '100%'
        }}
      >
        {renderItem(i)}
      </div>
    );
  }

  /**
   * 处理滚动事件
   * 更新scrollTop状态以触发重新渲染
   * @param {React.UIEvent<HTMLDivElement>} event - 滚动事件对象
   */
  const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
    setScrollTop(event.currentTarget.scrollTop);
  };

  return (
    <div
      ref={containerRef}
      className="virtual-list-container"
      style={{ height: `${containerHeight}px`, overflow: 'auto' }}
      onScroll={handleScroll}
    >
      <div
        className="virtual-list-inner"
        style={{ height: `${totalCount * itemHeight}px`, position: 'relative' }}
      >
        {items}
      </div>
    </div>
  );
};

export default VirtualList;